module jusone
using Merly
using JSON
import Distributed.@spawn
import JSONWebTokens

const Tokensecret = "df35aa4d9830756b94b3c5cf649de964"
u="hello"
server = Merly.app()
bytes = Merly.bytes
ok = Dict("code" => 0,"msg" => "success")
fail = Dict("code" => 1,"msg" => "error ")
Option = Union{T, Nothing} where T
Option2 = Union{T, Missing} where T
Option3 = Some{T} where T #something(opt)
json(s) = Merly.bytes(JSON.json(s))
Whitelist = ["/login"]

function router()
    @page "/" "Hello World!"
    @page "/hola/:usr>" "<b>Hello {{usr}}!</b>"

    @route GET "/get/:data>" begin
        "get this back: {{data}}"
    end

    @route POST "/post" begin
        "I did something!"
    end

    @route POST|PUT|DELETE "/" begin
        println("params: ",q.params)
        println("query: ",q.query)
        println("body: ",q.body)
        q.headers["Content-Type"]= "text/plain"
        "I did something!"
    end

    Get("/data", (q,req,res)->(begin
                                   ret = @async rand(0:10000) 
                                   ok["data"] =  "" * repr(fetch(ret))
                                   ok 
                               end))


    Post("/login", (q,req,res)->(begin
                                     println("params: ",q.params)
                                     println("query: ",q.query)
                                     println("body: ",q.body)
                                     claims_dict = Dict( "sub" => "1234567890", "name" => "John Doe", "iat" => 1516239022)
                                     encoding = JSONWebTokens.HS256(Tokensecret)
                                     jwt = JSONWebTokens.encode(encoding, claims_dict)
                                     ok["data"] = jwt
                                     ok
                                 end))
end
function bootservice(opt::Option2)
    local b::Option3  
    b = something(Some("ok")) |> Some
    ret = something(b) == nothing ? error("nothing") : b
end

function checkToken(req,res)
    tokens = filter(x-> lowercase(x.first) == "authorization" && startswith(x.second,"Bearer ") ,req.headers)
    encoding = JSONWebTokens.HS256(Tokensecret)
    userInfo = missing
    try
        userInfo = length(tokens) > 0 ? JSONWebTokens.decode(encoding, tokens[1].second[8:end]) : error("401")
    catch ex 
        res.status = 401
        res.body = json(Dict("code" => 401, "msg" => "no auth"))
        # @error ex
    end
    # @info userInfo
end

function middle(query, req,res)
    @info "body:" query,req.target
    if !(res.status in [404]) && !(req.target in Whitelist)
        checkToken(req,res)
    end
end

function run()
    @info "boot"
    @spawn bootservice(missing)
    router()
    server.useCORS(true)
    server.use(middle)
    server.start(Dict("host" => "127.0.0.1","port" => 8000))
end

end
